{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "635d8ebb",
   "metadata": {},
   "source": [
    "# Naive RAG\n",
    "\n",
    "- Author: [Youngjun cho](https://github.com/choincnp)\n",
    "- Design: [LeeYuChul](https://github.com/LeeYuChul)\n",
    "- Peer Review: \n",
    "- Proofread : [Chaeyoon Kim](https://github.com/chaeyoonyunakim)\n",
    "- This is a part of [LangChain Open Tutorial](https://github.com/LangChain-OpenTutorial/LangChain-OpenTutorial)\n",
    "\n",
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/17-LangGraph/02-Structures/02-LangGraph-Naive-RAG.ipynb)[![Open in GitHub](https://img.shields.io/badge/Open%20in%20GitHub-181717?style=flat-square&logo=github&logoColor=white)](https://github.com/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/17-LangGraph/02-Structures/02-LangGraph-Naive-RAG.ipynb)\n",
    "## Overview\n",
    "\n",
    "In this chapter, Section 02(Naive-RAG) through Section 05(Add-Query-Rewrite) is not an independent section, but cover one topic.\n",
    "\n",
    "We'll make a basic RAG on this section, and make more complicated RAG as sections goes by.\n",
    "\n",
    "### Table of Contents\n",
    "\n",
    "- [Overview](#overview)\n",
    "- [Environment Setup](#environment-setup)\n",
    "- [Procedure](#procedure)\n",
    "- [Creating a Basic PDF-Based Retrieval Chain](#creating-a-basic-pdf-based-retrieval-chain)\n",
    "- [Defining State](#defining-state)\n",
    "- [Defining Nodes](#defining-nodes)\n",
    "- [Creating the Graph](#creating-the-graph)\n",
    "- [Excuting the Graph](#executing-the-graph)\n",
    "\n",
    "### References\n",
    "\n",
    "- [LangGraph Streaming](https://python.langchain.com/docs/concepts/streaming/)\n",
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6c7aba4",
   "metadata": {},
   "source": [
    "## Environment Setup\n",
    "\n",
    "Setting up your environment is the first step. See the [Environment Setup](https://wikidocs.net/257836) guide for more details.\n",
    "\n",
    "\n",
    "**[Note]**\n",
    "\n",
    "The langchain-opentutorial is a package of easy-to-use environment setup guidance, useful functions and utilities for tutorials.\n",
    "Check out the  [```langchain-opentutorial```](https://github.com/LangChain-OpenTutorial/langchain-opentutorial-pypi) for more details."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "21943adb",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install langchain-opentutorial"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f25ec196",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install required packages\n",
    "from langchain_opentutorial import package\n",
    "\n",
    "package.install(\n",
    "    [\n",
    "        \"langsmith\",\n",
    "        \"langchain\",\n",
    "        \"langchain_core\",\n",
    "        \"langchain_community\",\n",
    "        \"langgraph\",\n",
    "        \"typing\",\n",
    "        \"langchain-opentutorial\"\n",
    "    ],\n",
    "    verbose=False,\n",
    "    upgrade=False,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "690a9ae0",
   "metadata": {},
   "source": [
    "You can set API keys in a ```.env``` file or set them manually.\n",
    "\n",
    "[Note] If you’re not using the ```.env``` file, no worries! Just enter the keys directly in the cell below, and you’re good to go."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "327c2c7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "from langchain_opentutorial import set_env\n",
    "\n",
    "# Attempt to load environment variables from a .env file; if unsuccessful, set them manually.\n",
    "if not load_dotenv():\n",
    "    set_env(\n",
    "        {\n",
    "            \"OPENAI_API_KEY\": \"\",\n",
    "            \"LANGCHAIN_API_KEY\": \"\",\n",
    "            \"LANGCHAIN_TRACING_V2\": \"true\",\n",
    "            \"LANGCHAIN_ENDPOINT\": \"https://api.smith.langchain.com\",\n",
    "            \"LANGCHAIN_PROJECT\": \"02-LangGraph-Naive-RAG\",  # set the project name same as the title\n",
    "        }\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa00c3f4",
   "metadata": {},
   "source": [
    "## Procedure\n",
    "\n",
    "Perform ```Naive RAG```, the basic RAG system which has 2 progress, **Retrieve** and **Generate** .\n",
    "\n",
    "You can see the structure in the image below.\n",
    "\n",
    "![](./assets/02-langgraph-naive-rag.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56b83578",
   "metadata": {},
   "source": [
    "## Creating a Basic PDF-Based Retrieval Chain\n",
    "\n",
    "This section creates a Retrieval Chain based on a **PDF document** . It is the simplest structure of a Retrieval Chain.\n",
    "\n",
    "In ```LangGraph``` , Retrievers and Chains are created separately. This allows detailed processing for each node."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b8ea5466",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d8a4062a",
   "metadata": {},
   "outputs": [],
   "source": [
    "from rag.pdf import PDFRetrievalChain\n",
    "\n",
    "# Load the PDF document\n",
    "pdf = PDFRetrievalChain([\"data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf\"]).create_chain()\n",
    "\n",
    "# Create retriever and chain\n",
    "pdf_retriever = pdf.retriever\n",
    "pdf_chain = pdf.chain"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34f7150f",
   "metadata": {},
   "source": [
    "First, use the ```pdf_retriever``` to fetch search results.\n",
    "\n",
    "You can control the quantity to retrieve, by changing ```self_k``` argument in ```pdf.py``` file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6c98f04a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(id='76d10387-a006-4d7c-8bd1-c316831d6094', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 14, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='activities. So far, however, AI applications in healthcare have been potential. Specific healthcare training should be provided to data\\nconfined to administrative tasks (i.e., Natural Language Processing scientists working in hospitals so that they can better understand'),\n",
       " Document(id='f4f78deb-c8d9-4c84-a3e4-a91b0477413d', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 14, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='are great, as more use of AI in research and development could\\nHealthcare is arguably the sector where AI could make the lead to a more personalised healthcare based on patients’ data.'),\n",
       " Document(id='e393ec31-5738-4454-aab0-bf1f33ec1d18', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 10, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='intermediate / professional users (i.e., healthcare professionals). the safety of employees. The key application of AI is certainly in\\nThis is a matter of privacy and personal data protection, of building predictive maintenance. Yet, the more radical transformation of'),\n",
       " Document(id='693acf63-9fbf-4e71-9128-71b230dcd17f', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 15, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='Remote sible, as AI solutions can increasingly divert patients ning healthcare professionals, starting from the simple\\nhealthcare to appropriate solutions for their specific symptoms tasks and diagnostic appointments.\\nand underlying conditions.\\n16'),\n",
       " Document(id='764ba481-f984-47e9-b86b-98250eda7ad1', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 14, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='same. The Covid-19 crisis has shown how strained our National\\nHealthcare Systems are, and AI solutions could help meet the cur- AI in the healthcare faces organisational and skill challenges. One'),\n",
       " Document(id='c0f68d31-3ebf-45f7-bf6c-cef790cb6f92', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 3, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='advanced robots, autonomous cars, drones or Internet of Things place, a recent EIT Health Report envisages more in healthcare in\\napplications)”. Broad AI definitions cover several technologies, in- the near future, such as remote monitoring, AI-powered alerting'),\n",
       " Document(id='8594b8a3-aef5-44ae-93aa-7f1d5afeaaa3', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 21, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='EIT Health and McKinsey & Company, (2020), Transforming healthcare with AI. Impact Scherer, M. (2016). Regulating Artificial Intelligence Systems: Risks, Challenges, Compe-'),\n",
       " Document(id='98d019bc-1a7e-4273-8eac-eff09d7bf756', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 15, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='very sensitive. An extensive use to feed AI tools can the use of patient’s data in the hospitals that deploy\\nHealth data raise many concerns. Data ownership is also an issue AI-powered applications. The patients should be aware'),\n",
       " Document(id='b63de5ec-3554-488f-a4c0-1975c0c9e39f', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 14, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='to extract information from clinical notes or predictive scheduling healthcare practitioners needs. In addition, at the regulatory le-\\nof the visits) and diagnostic (machine and deep learning applied to vel it is important that new AI regulation is harmonised with other'),\n",
       " Document(id='7c4c1675-87ad-47ba-8df1-39e8036cf6c2', metadata={'source': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'file_path': 'data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf', 'page': 14, 'total_pages': 24, 'CreationDate': \"D:20200922223534+02'00'\", 'Creator': 'Adobe InDesign 15.1 (Macintosh)', 'ModDate': \"D:20200922223544+02'00'\", 'Producer': 'Adobe PDF Library 15.0', 'Trapped': 'False'}, page_content='greatest impact in addressing societal challenges. Given rising de- A second challenge is that of finding a common language and un-\\nmands and costs, AI could help doing more and better with the derstanding between data experts and healthcare professionals.')]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "search_result = pdf_retriever.invoke(\n",
    "    \"Where has the application of AI in healthcare been confined to so far?\"\n",
    ")\n",
    "search_result"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "abf7eabc",
   "metadata": {},
   "source": [
    "Pass the search result as context to the chain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "80f1eea5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The application of AI in healthcare has so far been confined primarily to administrative tasks, such as Natural Language Processing for extracting information from clinical notes and predictive scheduling. There is potential for more extensive use in research and development, but significant applications remain limited.\n",
      "\n",
      "**Source**\n",
      "- data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf (page 14)\n"
     ]
    }
   ],
   "source": [
    "# Generate an answer based on the search results\n",
    "answer = pdf_chain.invoke(\n",
    "    {\n",
    "        \"question\": \"Where has the application of AI in healthcare been confined to so far?\",\n",
    "        \"context\": search_result,\n",
    "        \"chat_history\": [],\n",
    "    }\n",
    ")\n",
    "print(answer)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0430cc3f",
   "metadata": {},
   "source": [
    "## Defining State\n",
    "\n",
    "```State``` defines the **shared state** among the nodes and another nodes.\n",
    "\n",
    "Typically, the ```TypedDict``` format is used."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4e392f46",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Annotated, TypedDict\n",
    "from langgraph.graph.message import add_messages\n",
    "\n",
    "# Define GraphState\n",
    "class GraphState(TypedDict):\n",
    "    question: Annotated[str, \"Question\"]  # Question\n",
    "    context: Annotated[str, \"Context\"]  # Search results from the document\n",
    "    answer: Annotated[str, \"Answer\"]  # Answer\n",
    "    messages: Annotated[list, add_messages]  # Messages (accumulated list)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9e26176",
   "metadata": {},
   "source": [
    "## Defining Nodes\n",
    "\n",
    "```Nodes``` : These are nodes that handle each stage, typically implemented as Python functions. Inputs and outputs are the State values.\n",
    "\n",
    "[ **Note** ]  \n",
    "- A ```State``` is taken as input, performs the defined logic, and returns an **updated** ```State``` ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "2892e164",
   "metadata": {},
   "outputs": [],
   "source": [
    "from rag.utils import format_docs\n",
    "from langchain_opentutorial.messages import messages_to_history\n",
    "\n",
    "# Node that retrieve document\n",
    "def retrieve_document(state: GraphState) -> GraphState:\n",
    "    # Get the question from the state\n",
    "    latest_question = state[\"question\"]\n",
    "\n",
    "    # Search the document to find relevant sections\n",
    "    retrieved_docs = pdf_retriever.invoke(latest_question)\n",
    "\n",
    "    # Format the retrieved documents (to input into a prompt)\n",
    "    retrieved_docs = format_docs(retrieved_docs)\n",
    "    \n",
    "    # Save the retrieved documents in the key named context\n",
    "    return {\"context\": retrieved_docs}\n",
    "\n",
    "\n",
    "# Node that generate answer\n",
    "def llm_answer(state: GraphState) -> GraphState:\n",
    "    # Get the question from the state\n",
    "    latest_question = state[\"question\"]\n",
    "\n",
    "    # Get the retrieved documents from the state\n",
    "    context = state[\"context\"]\n",
    "\n",
    "    # Call the chain to generate an answer\n",
    "    response = pdf_chain.invoke(\n",
    "        {\n",
    "            \"question\": latest_question,\n",
    "            \"context\": context,\n",
    "            \"chat_history\": messages_to_history(state[\"messages\"]),\n",
    "        }\n",
    "    )\n",
    "\n",
    "    # Save the generated answer and (user question, answer) messages in the state\n",
    "    return {\n",
    "        \"answer\": response,\n",
    "        \"messages\": [(\"user\", latest_question), (\"assistant\", response)],\n",
    "    }"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "303edffd",
   "metadata": {},
   "source": [
    "## Creating the Graph\n",
    "\n",
    "```Edges``` : Python functions that determine the next ```Node``` to execute based on the **current** ```State``` .\n",
    "\n",
    "There can be general edges and conditional edges."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "4ea7f66c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph.graph import END, StateGraph\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "\n",
    "# Create a graph\n",
    "workflow = StateGraph(GraphState)\n",
    "\n",
    "# Define nodes\n",
    "workflow.add_node(\"retrieve\", retrieve_document)\n",
    "workflow.add_node(\"llm_answer\", llm_answer)\n",
    "\n",
    "# Define edges\n",
    "workflow.add_edge(\"retrieve\", \"llm_answer\")  # Retrieval -> Answer generation\n",
    "workflow.add_edge(\"llm_answer\", END)  # Answer generation -> End\n",
    "\n",
    "# Set entry point for the graph\n",
    "workflow.set_entry_point(\"retrieve\")\n",
    "\n",
    "# Set up a checkpointer\n",
    "memory = MemorySaver()\n",
    "\n",
    "# Compile the graph\n",
    "app = workflow.compile(checkpointer=memory)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f5b7377",
   "metadata": {},
   "source": [
    "Visualize the compiled graph."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "74add1cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from langchain_opentutorial.graphs import visualize_graph\n",
    "\n",
    "visualize_graph(app) "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cf924d4",
   "metadata": {},
   "source": [
    "## Executing the Graph\n",
    "\n",
    "- The ```config``` parameter provides configuration informations necessary for graph execution.\n",
    "- ```recursion_limit``` : Sets the maximum recursion depth for graph execution.\n",
    "- ```inputs``` : Provides the input data for the graph execution.\n",
    "\n",
    "The ```stream_graph``` function below streams only specific nodes.\n",
    "\n",
    "You can easily check the **streaming output** of a **specific node** ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b6765d83",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "==================================================\n",
      "🔄 Node: \u001b[1;36mretrieve\u001b[0m 🔄\n",
      "- - - - - - - - - - - - - - - - - - - - - - - - - \n",
      "\u001b[1;32mcontext\u001b[0m:\n",
      "<document><content>activities. So far, however, AI applications in healthcare have been potential. Specific healthcare training should be provided to data\n",
      "confined to administrative tasks (i.e., Natural Language Processing scientists working in hospitals so that they can better understand</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>15</page></document>\n",
      "<document><content>are great, as more use of AI in research and development could\n",
      "Healthcare is arguably the sector where AI could make the lead to a more personalised healthcare based on patients’ data.</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>15</page></document>\n",
      "<document><content>intermediate / professional users (i.e., healthcare professionals). the safety of employees. The key application of AI is certainly in\n",
      "This is a matter of privacy and personal data protection, of building predictive maintenance. Yet, the more radical transformation of</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>11</page></document>\n",
      "<document><content>Remote sible, as AI solutions can increasingly divert patients ning healthcare professionals, starting from the simple\n",
      "healthcare to appropriate solutions for their specific symptoms tasks and diagnostic appointments.\n",
      "and underlying conditions.\n",
      "16</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>16</page></document>\n",
      "<document><content>same. The Covid-19 crisis has shown how strained our National\n",
      "Healthcare Systems are, and AI solutions could help meet the cur- AI in the healthcare faces organisational and skill challenges. One</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>15</page></document>\n",
      "<document><content>advanced robots, autonomous cars, drones or Internet of Things place, a recent EIT Health Report envisages more in healthcare in\n",
      "applications)”. Broad AI definitions cover several technologies, in- the near future, such as remote monitoring, AI-powered alerting</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>4</page></document>\n",
      "<document><content>EIT Health and McKinsey & Company, (2020), Transforming healthcare with AI. Impact Scherer, M. (2016). Regulating Artificial Intelligence Systems: Risks, Challenges, Compe-</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>22</page></document>\n",
      "<document><content>very sensitive. An extensive use to feed AI tools can the use of patient’s data in the hospitals that deploy\n",
      "Health data raise many concerns. Data ownership is also an issue AI-powered applications. The patients should be aware</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>16</page></document>\n",
      "<document><content>to extract information from clinical notes or predictive scheduling healthcare practitioners needs. In addition, at the regulatory le-\n",
      "of the visits) and diagnostic (machine and deep learning applied to vel it is important that new AI regulation is harmonised with other</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>15</page></document>\n",
      "<document><content>greatest impact in addressing societal challenges. Given rising de- A second challenge is that of finding a common language and un-\n",
      "mands and costs, AI could help doing more and better with the derstanding between data experts and healthcare professionals.</content><source>data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf</source><page>15</page></document>\n",
      "==================================================\n",
      "\n",
      "==================================================\n",
      "🔄 Node: \u001b[1;36mllm_answer\u001b[0m 🔄\n",
      "- - - - - - - - - - - - - - - - - - - - - - - - - \n",
      "\u001b[1;32manswer\u001b[0m:\n",
      "The application of AI in healthcare has so far been confined primarily to administrative tasks, such as Natural Language Processing for extracting information from clinical notes and predictive scheduling. \n",
      "\n",
      "**Source**\n",
      "- data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf (page 15)\n",
      "('user', 'Where has the application of AI in healthcare been confined to so far?')\n",
      "('assistant', 'The application of AI in healthcare has so far been confined primarily to administrative tasks, such as Natural Language Processing for extracting information from clinical notes and predictive scheduling. \\n\\n**Source**\\n- data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf (page 15)')\n",
      "==================================================\n"
     ]
    }
   ],
   "source": [
    "from langchain_core.runnables import RunnableConfig\n",
    "from langchain_opentutorial.messages import invoke_graph, stream_graph, random_uuid\n",
    "\n",
    "# Configure settings (recursion limit, thread_id)\n",
    "config = RunnableConfig(recursion_limit=20, configurable={\"thread_id\": random_uuid()})\n",
    "\n",
    "# Question input\n",
    "inputs = GraphState(\n",
    "    question=\"Where has the application of AI in healthcare been confined to so far?\"\n",
    ")\n",
    "\n",
    "# Execute the graph\n",
    "invoke_graph(app, inputs, config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "07a4505e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "==================================================\n",
      "🔄 Node: \u001b[1;36mllm_answer\u001b[0m 🔄\n",
      "- - - - - - - - - - - - - - - - - - - - - - - - - \n",
      "The application of AI in healthcare has so far been confined primarily to administrative tasks, such as Natural Language Processing for extracting information from clinical notes and predictive scheduling.\n",
      "\n",
      "**Source**\n",
      "- data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf (page 15)"
     ]
    }
   ],
   "source": [
    "# Stream the graph outputs\n",
    "stream_graph(app, inputs, config)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "405b1c79",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Question: Where has the application of AI in healthcare been confined to so far?\n",
      "============================================================\n",
      "Answer:\n",
      "The application of AI in healthcare has so far been confined primarily to administrative tasks, such as Natural Language Processing for extracting information from clinical notes and predictive scheduling.\n",
      "\n",
      "**Source**\n",
      "- data/A European Approach to Artificial Intelligence - A Policy Perspective.pdf (page 15)\n"
     ]
    }
   ],
   "source": [
    "outputs = app.get_state(config).values\n",
    "\n",
    "print(f'Question: {outputs[\"question\"]}')\n",
    "print(\"===\" * 20)\n",
    "print(f'Answer:\\n{outputs[\"answer\"]}')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain-opentutorial-lQfVMvH8-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
